<template>
  <div class="container" ref="containerRef">
      <slot></slot>
    <Teleport to="body">
      <transition
        @beforeEnter="handleBeforeEnter"
        @enter="handleEnter"
        @afterEnter="handleAfterEnter"
      >
        <div 
          v-if="showMenu" 
          class="context-menu"
          :style="{
            left: x + 'px',
            top: y + 'px'
          }"
        >
          <div
            @click="handleClick(item)"
            class="menu-item"
            v-for="item in menu"
            :key="item.label"
          >
            {{ item.label }}
          </div>
        </div>
      </transition>
    </Teleport>
  </div>
</template>

<script>
import Teleport from './Teleport.vue'
export default {
  name: 'ContextMenu',
  components: {
    Teleport
  }, 
  props: {
    menu: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      x: 0,
      y: 0,
      showMenu: false
    }
  },
  watch: {
    showMenu(v) {
      if (v) {
        window.addEventListener('click', this.closeMenu)
        window.addEventListener('contextmenu', this.closeMenu, true)
      } else {
        window.removeEventListener('click', this.closeMenu)
        window.removeEventListener('contextmenu', this.closeMenu, true)
      }
    }
  },
  mounted() {
    this.$refs.containerRef.addEventListener('contextmenu', this.openMenu)
  },
  unmounted() {
    this.$refs.containerRef.removeEventListener('contextmenu', this.openMenu)
  },
  methods: {
    handleClick(item) {
      this.showMenu = false
      this.$emit('select', item)
    },
    handleBeforeEnter(el) {
      el.style.height = 0
    },
    handleEnter(el) {
      el.style.height = 'auto'
      const h = el.clientHeight
      el.style.height = 0
      requestAnimationFrame(() => {
        el.style.height = h + 'px'
        el.style.transition = '.2s'
      })
    },
    handleAfterEnter(el) {
      el.style.transition = 'none'
    },
    openMenu(e) {
      e.preventDefault()
      e.stopPropagation()
      this.showMenu = true
      this.x = e.clientX
      this.y = e.clientY
    },
    closeMenu() {
      this.showMenu = false
    }
  }
}
</script>

<style scoped>
.container {
  display: contents;
}
.context-menu {
  position: fixed;
  z-index: 3000;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  background-color: #fff;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  overflow: hidden;
  .menu-item {
    padding: 0 10px;
    color: #606266;
    font-size: 14px;
    line-height: 30px;
    cursor: pointer;
    &:hover {
      background-color: #f5f7fa;
    }
  }
}
</style>